/**
 * @file    invt_can.c
 * @brief   逆变器协议-英威腾-CAN通信接口V6.0
 * @author  Liuwei
 * @version 1.0.1
 * @date    2023-04-30
 * 
 * @copyright Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version   <th>Author   <th>Description
 * <tr><td>2023-04-30 <td>1.0.1     <td>Liuwei   <td>首次创建
 * </table>
 */

/* includes ------------------------------------------------------------------*/
#include "sma_can.h"
#include "If_can.h"
#include "var_mng.h"
#include "param_mng.h"
#include "cfg_prj.h"
#include "diagnosis.h"
#include "parallel.h"
/* macro/define --------------------------------------------------------------*/

/* typedef -------------------------------------------------------------------*/
typedef struct 
{
    uint16_t can_id;      /* !< 报文ID */
    uint16_t send_cycle; /* !< 发送周期 */
    uint16_t send_cnt;   /* !< 计时器 */
    void(*pfunc_get_frame_msg)(can_frame_type *);
}send_frame_type;

typedef struct 
{
    uint16_t can_id;      /* !< 报文ID */
    uint8_t(*pfunc_recv_frame_msg)(can_frame_type , can_frame_type *);
}recv_frame_type;

typedef union
{
	uint8_t byte_data;
	struct
	{
		uint8_t chg_en : 1;
        uint8_t dsg_en : 1;
        uint8_t force_chg : 1;
	}name;
}ask_cmd_type;

typedef union 
{
    uint32_t word_data;
    struct 
    {
        uint32_t general_alarm : 2;
        uint32_t ov_alarm : 2;
        uint32_t uv_alarm : 2;
        uint32_t otd_alarm : 2;
		
        uint32_t utd_alarm : 2;
        uint32_t otc_alarm : 2;
		uint32_t utc_alarm : 2;
		uint32_t ocd_alarm : 2;
		
		uint32_t occ_alarm : 2;
		uint32_t contactor_alarm : 2; /*!< 接触器告警 */
		uint32_t sc_alarm : 2;
		uint32_t bsm_int_alarm : 2;
		
		uint32_t cell_blc_alarm : 2;
		uint32_t reserved : 6;
	}name;
}alarm_msg_type;

typedef struct
{
	uint32_t word_data;
    struct 
    {
		uint32_t general_warn : 2;
        uint32_t ov_warn : 2;
        uint32_t uv_warn : 2;
        uint32_t otd_warn : 2;
		
        uint32_t utd_warn : 2;
        uint32_t otc_warn : 2;
		uint32_t utc_warn : 2;
		uint32_t ocd_warn : 2;
		
		uint32_t occ_warn : 2;
		uint32_t contactor_warn : 2; /*!< 接触器告警 */
		uint32_t sc_warn : 2;
		uint32_t bsm_int_warn : 2;
		
		uint32_t cell_blc_warn : 2;
		uint32_t system_status : 2;
		uint32_t reserved2 : 4;
    }name;
}warn_msg_type;

/* local functions -----------------------------------------------------------*/
static void can_get_0x150_msg(can_frame_type *can_msg);
static void can_get_0x151_msg(can_frame_type *can_msg);
static void can_get_0x180_msg(can_frame_type *can_msg);
static void can_get_0x181_msg(can_frame_type *can_msg);
static void can_get_0x182_msg(can_frame_type *can_msg);
static void can_get_0x183_msg(can_frame_type *can_msg);
static void can_get_0x184_msg(can_frame_type *can_msg);
static void can_get_0x185_msg(can_frame_type *can_msg);
static void can_get_0x186_msg(can_frame_type *can_msg);
static void can_get_0x187_msg(can_frame_type *can_msg);

static uint8_t can_recv_0x100_msg(can_frame_type can_recv,can_frame_type *can_send);
static uint8_t can_recv_0x101_msg(can_frame_type can_recv,can_frame_type *can_send);
static uint8_t can_recv_0x102_msg(can_frame_type can_recv,can_frame_type *can_send);
/* static variables ----------------------------------------------------------*/
static send_frame_type send_frame_list[] = 
{
    {0x180 , 1000 , 0 ,can_get_0x180_msg },
    {0x181 , 1000 , 0 ,can_get_0x181_msg },
    {0x182 , 1000 , 0 ,can_get_0x182_msg },
    {0x183 , 1000 , 0 ,can_get_0x183_msg },
    {0x184 , 1000 , 0 ,can_get_0x184_msg },
    {0x185 , 1000 , 0 ,can_get_0x185_msg },
    {0x186 , 1000 , 0 ,can_get_0x186_msg },
    {0x187 , 1000 , 0 ,can_get_0x187_msg },
};

#define CAN_LIST_NUM     (sizeof(send_frame_list)/sizeof(send_frame_type))

static recv_frame_type recv_frame_list[] = 
{
    {0x100 ,  can_recv_0x100_msg},
    {0x101 ,  can_recv_0x101_msg},
    {0x102 ,  can_recv_0x102_msg},
};

#define RECV_LIST_NUM    (sizeof(recv_frame_list)/sizeof(recv_frame_type))
/* global variables ----------------------------------------------------------*/

/** ------------------------------------------------------------------------- *
  *                             Global function
 ** ------------------------------------------------------------------------- */
/**
 * @brief  获取需要发送的数据信息
 * @param  cycle
 * @param  can_buf
 * @return uint8_t 
 */
uint8_t invt_can_deal_msg(uint32_t cycle , can_frame_type *can_buf , uint8_t recv_num ,const can_frame_type *recv_msg)
{
    uint8_t i = 0;
	uint8_t j = 0;
    uint8_t msg_num = 0;

    for( i = 0; i < CAN_LIST_NUM; ++ i)
    {
        send_frame_list[i].send_cnt += cycle;
        if(send_frame_list[i].send_cnt >= send_frame_list[i].send_cycle)
        {
            send_frame_list[i].send_cnt = 0;
            send_frame_list[i].pfunc_get_frame_msg(&can_buf[msg_num ++]); 
        }
    }

    for( i = 0;i < recv_num; ++ i)
    {
        for( j = 0;j < RECV_LIST_NUM; ++ j)
        if(recv_frame_list[j].can_id == recv_msg[i].id)
        {
            msg_num += recv_frame_list[j].pfunc_recv_frame_msg(recv_msg[i] , &can_buf[msg_num]);
        }
    }

    return msg_num;
}

/** ------------------------------------------------------------------------- *
  *                              Local function
 ** ------------------------------------------------------------------------- */
static void can_get_0x150_msg(can_frame_type *can_msg)
{
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x150;

    can_msg->data.half_buf[0] = 0x01;
    can_msg->data.half_buf[1] = 0;
    can_msg->data.half_buf[2] = 0;
    can_msg->data.half_buf[3] = 0;
}

static void can_get_0x151_msg(can_frame_type *can_msg)
{
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x151;

    can_msg->data.byte_buf[0] = SOFT_VER_MAIN;
    can_msg->data.byte_buf[1] = SOFT_VER_RELEASE;
    can_msg->data.half_buf[1] = var_get_data(VAR_ID_HARD_VER);
    can_msg->data.half_buf[2] = param_get_data(PAR_ID_CB_CELL_NUM);
    can_msg->data.half_buf[3] = param_get_data(PAR_ID_CB_CELL_NUM) * 32;
}

static void can_get_0x180_msg(can_frame_type *can_msg)
{
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x180;

    can_msg->data.half_buf[0] = var_get_data(VAR_ID_TP_SOP_CV); /*0:正常 1:强制充电 2:强制待机 */
    can_msg->data.half_buf[1] = var_get_data(VAR_ID_TP_SOP_DV);
    can_msg->data.half_buf[2] = var_get_data(VAR_ID_TP_SOP_CC);
    can_msg->data.half_buf[3] = var_get_data(VAR_ID_TP_SOP_DC);
}

extern master_data_type master_data_reg;
static void can_get_0x181_msg(can_frame_type *can_msg)
{
	int16_t sys_curr = 0;
	uint8_t soh = 0;
	/* 告警及保护信息 */
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x181;

    can_msg->data.half_buf[0] = master_data_reg.avg_batt_volt * 0.1;
	sys_curr = master_data_reg.total_bus_curr * 0.1;
    can_msg->data.half_buf[1] = sys_curr;
    can_msg->data.half_buf[2] = master_data_reg.avg_soc;
	soh = var_get_data(VAR_ID_TP_SOH);
	if(soh > 100)
		soh = 100;
    can_msg->data.half_buf[3] = soh;
}

static void can_get_0x182_msg(can_frame_type *can_msg)
{
    ask_cmd_type ask_cmd = {0};
    uint8_t sys_status = 0;

    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x182;

   
    if(master_data_reg.total_bus_curr > 0)
        sys_status = 0x01;
    else if(master_data_reg.total_bus_curr < 0)
        sys_status = 0x02;
    else
        sys_status = 0x00;

    ask_cmd.name.chg_en = parallel_get_pcs_ctrl(PARALLEL_PCS_CHG_EN);
    ask_cmd.name.dsg_en = parallel_get_pcs_ctrl(PARALLEL_PCS_DSG_EN);
    ask_cmd.name.force_chg = parallel_get_pcs_ctrl(PARALLEL_PCS_FROCE_CHG1);
    can_msg->data.byte_buf[0] = ask_cmd.byte_data;
    can_msg->data.byte_buf[0] = sys_status;
    can_msg->data.half_buf[1] = 0;
    can_msg->data.half_buf[2] = 0;
    can_msg->data.half_buf[3] = 0;
}

static void can_get_0x183_msg(can_frame_type *can_msg)
{
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x183;

    can_msg->data.half_buf[0] = var_get_data(VAR_ID_TP_MAXC_VOLT);
    can_msg->data.half_buf[1] = var_get_data(VAR_ID_TP_MINC_VOLT);
    can_msg->data.half_buf[2] = var_get_data(VAR_ID_TP_MAXT_VAL) - 2731;
    can_msg->data.half_buf[3] = var_get_data(VAR_ID_TP_MINT_VAL) - 2731;
}

static void can_get_0x184_msg(can_frame_type *can_msg)
{
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x184;
    
    can_msg->data.half_buf[0] = var_get_data(VAR_ID_TP_MAXC_SN);
    can_msg->data.half_buf[1] = var_get_data(VAR_ID_TP_MINC_SN);
    can_msg->data.half_buf[2] = var_get_data(VAR_ID_TP_MAXT_SN);
    can_msg->data.half_buf[3] = var_get_data(VAR_ID_TP_MINT_SN);
}

static void can_get_0x185_msg(can_frame_type *can_msg)
{
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x185;
    
    can_msg->data.word_buf[0] = 0; 
    can_msg->data.word_buf[1] = 0;
}

static void can_get_0x186_msg(can_frame_type *can_msg)
{
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x186;
    
    can_msg->data.half_buf[0] = 0; /*0:正常 1:强制充电 2:强制待机 */
    can_msg->data.half_buf[1] = 0;
    can_msg->data.byte_buf[4] = master_data_reg.total_prp_msg.bit.otc;
    can_msg->data.byte_buf[5] = master_data_reg.total_prp_msg.bit.otd;
    can_msg->data.byte_buf[6] = master_data_reg.total_prp_msg.bit.utc;
    can_msg->data.byte_buf[7] = master_data_reg.total_prp_msg.bit.utd;
}

static void can_get_0x187_msg(can_frame_type *can_msg)
{
    can_msg->frame_type = CAN_FRAME_DATA;
    can_msg->id_type = CAN_ID_STD;
    can_msg->dlc = 8;
    can_msg->id = 0x187;
    
    can_msg->data.byte_buf[0] = master_data_reg.total_prp_msg.bit.occ; 
    can_msg->data.byte_buf[1] = master_data_reg.total_prp_msg.bit.ocd;
    can_msg->data.byte_buf[2] = master_data_reg.total_prp_msg.bit.vdiff; 
    can_msg->data.byte_buf[3] = master_data_reg.total_prp_msg.bit.tdiff;
    can_msg->data.byte_buf[4] = master_data_reg.total_prp_msg.bit.socl;
    can_msg->data.byte_buf[5] = 0;
    can_msg->data.byte_buf[6] = 0;
    can_msg->data.byte_buf[7] = 0;
}

static uint8_t can_recv_0x100_msg(can_frame_type can_recv,can_frame_type *can_send)
{
    can_get_0x150_msg(can_send);
    can_send ++ ;
    can_get_0x151_msg(can_send);

    return 2;
}

static uint8_t can_recv_0x101_msg(can_frame_type can_recv,can_frame_type *can_send)
{
    // uint8_t year = 0;
    // uint8_t mon = 0;
    // uint8_t date = 0;
    // uint8_t hour = 0;
    // uint8_t min = 0;
    // uint8_t sec = 0;

    // year = can_recv.data.byte_buf[0];
    // mon = can_recv.data.byte_buf[1];
    // date = can_recv.data.byte_buf[2];
    // hour = can_recv.data.byte_buf[3];
    // min = can_recv.data.byte_buf[4];
    // sec = can_recv.data.byte_buf[5];

    return 0;
}

static uint8_t can_recv_0x102_msg(can_frame_type can_recv,can_frame_type *can_send)
{
    //
    return 0;
}

/********** Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD *********/


